from typing import Optional

from fastapi import FastAPI, Request, HTTPException
import jwt
from starlette import status
from starlette.middleware.base import BaseHTTPMiddleware

from config import appSettings

from api.router.model.user_model import User

app = FastAPI()

class AuthMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request: Request, call_next):
        auth = request.headers.get("x-token")
        uri = request.url.path
        # 过滤校验路由
        no_check_uri = appSettings.jwt_no_check_uris.split(",")
        print(uri)
        if uri in no_check_uri:
            # if uri not in ['/users/']:
            return await call_next(request)
        if not auth:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED, detail="Authorization header is missing",
                headers={"WWW-Authenticate": "Bearer"})
        try:
            deploy = jwt.decode(auth, appSettings.jwt_secret_key, algorithms=appSettings.jwt_algorithms)
            user = User(**deploy)
        except jwt.DecodeError:
            return HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST, detail="Authorization failed",
                headers={"WWW-Authenticate": "Bearer"})

@app.middleware("http")
async def verify_auth(request: Request, call_next):
    auth = request.headers.get("x-token")
    # 过滤校验路由
    no_check_uri = appSettings.jwt_no_check_uris.split(",")
    if auth in no_check_uri:
        return await call_next(request)
    if not auth:
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED, detail="Authorization header is missing",
            headers={"WWW-Authenticate": "Bearer"})
    try:
        deploy = jwt.decode(auth, appSettings.jwt_secret_key, algorithms=Optional[appSettings.jwt_algorithm])
        user = User(**deploy)
    except jwt.JWTDecodeError:
        return HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST, detail="Authorization failed",
            headers={"WWW-Authenticate": "Bearer"})
    print(user)
    request.state.user = user
    return await call_next(request)
